package Function;

import FCRendering.FCRMaster;
import VWorldGameStudio.*;
import com.google.gson.Gson;
import lombok.Getter;
import socket.FCRSocketConstant;
import socket.protocol.IProtocolServer;
import utils.FCMixUtil;

import java.util.*;
import java.util.function.BiConsumer;

import static FCRendering.FCRMaster.*;

public class FCMutilPlaySender {

    private IProtocolServer plcInterface;
    private Gson gson = new Gson();
    @Getter
    private String socketKey;
    public FCMutilPlaySender(String who, IProtocolServer inf) {
        socketKey = who;
        plcInterface = inf;
        System.out.println("FCMutilPlaySender "+socketKey);
    }

    //透传数据给其他玩家
    public void throughTransmissionSend(int cmd, byte[] param){
        plcInterface.sendData(socketKey,cmd, param);
    }

    //TODO 只能服务端调用
    public void sendAllPlayerAndTeam(int cmd) {
        ArrayList<FCPlayerInfo> fcPlayerInfos = new ArrayList<>();
        fcPlayerInfos.add(FCRMaster.player1);
        FCMutilPlayCache.gamePlayers.forEach(new BiConsumer<String, FCPlayerInfo>() {
            @Override
            public void accept(String s, FCPlayerInfo playerInfo) {
                fcPlayerInfos.add(playerInfo);
            }
        });
        String bigData = gson.toJson(fcPlayerInfos);
        String compress = FCMixUtil.compress(bigData);
        plcInterface.sendData(socketKey,cmd, compress.getBytes());
        //和坦克
        sendAllTanksSync();
    }

    public void sendPlayerAndTeam(int cmd) {
        ArrayList<FCPlayerInfo> fcPlayerInfos = new ArrayList<>();
        fcPlayerInfos.add(FCRMaster.player1);
        for (int i = 0; i < FCMutilPlayCache.getTeamMembers().size(); i++) {
            FCRPlayerLink link = FCMutilPlayCache.getTeamMembers().get(i);
            FCPlayerInfo info = FCMutilPlayCache.findPlayerByName(link.curPlayerHostUID, link.curPlayerName);
            fcPlayerInfos.add(info);
        }
        plcInterface.sendData(socketKey,cmd, gson.toJson(fcPlayerInfos).getBytes());
        //和坦克
        sendTanksSync();
    }

    //同步一些人物血量等的
    public void syncOnePlayerState(List<FCPlayerInfo> pl) {
        ArrayList<FCPlayerTransport> transports = new ArrayList<>(pl.size());
        for(FCPlayerInfo p: pl){
            transports.add(new FCPlayerTransport(p));
        }
        plcInterface.sendData(socketKey, FCRSocketConstant.COMMON_CHANGE_PLAYER_LIMIT, gson.toJson(transports).getBytes());
    }

    private void fillMovingData(byte[] data, int offset, FCPlayerInfo playerInfo) {
        int coox = playerInfo.getPlayer1x();
        int cooy = playerInfo.getPlayer1y();
        data[3 + offset] = (byte) (coox & 0xff);
        data[2 + offset] = (byte) ((coox & 0xff00) >> 8);
        data[1 + offset] = (byte) ((coox & 0xff0000) >> 16);
        data[0 + offset] = (byte) ((coox & 0xff000000) >> 24);
        data[7 + offset] = (byte) (cooy & 0xff);
        data[6 + offset] = (byte) ((cooy & 0xff00) >> 8);
        data[5 + offset] = (byte) ((cooy & 0xff0000) >> 16);
        data[4 + offset] = (byte) ((cooy & 0xff000000) >> 24);
        int n = playerInfo.getPianYiX();
        int m = playerInfo.getPianYiY();
        data[11 + offset] = (byte) (n & 0xff);
        data[10 + offset] = (byte) ((n & 0xff00) >> 8);
        data[9 + offset] = (byte) ((n & 0xff0000) >> 16);
        data[8 + offset] = (byte) ((n & 0xff000000) >> 24);
        data[15 + offset] = (byte) (m & 0xff);
        data[14 + offset] = (byte) ((m & 0xff00) >> 8);
        data[13 + offset] = (byte) ((m & 0xff0000) >> 16);
        data[12 + offset] = (byte) ((m & 0xff000000) >> 24);
        int cood = playerInfo.getActionDir();
        int coon = playerInfo.getActionNum();
        data[19 + offset] = (byte) (cood & 0xff);
        data[18 + offset] = (byte) ((cood & 0xff00) >> 8);
        data[17 + offset] = (byte) ((cood & 0xff0000) >> 16);
        data[16 + offset] = (byte) ((cood & 0xff000000) >> 24);
        data[23 + offset] = (byte) (coon & 0xff);
        data[22 + offset] = (byte) ((coon & 0xff00) >> 8);
        data[21 + offset] = (byte) ((coon & 0xff0000) >> 16);
        data[20 + offset] = (byte) ((coon & 0xff000000) >> 24);
        int lastWX = playerInfo.getLastInWorldMapX();
        int lastWY = playerInfo.getLastInWorldMapY();
        data[27 + offset] = (byte) (lastWX & 0xff);
        data[26 + offset] = (byte) ((lastWX & 0xff00) >> 8);
        data[25 + offset] = (byte) ((lastWX & 0xff0000) >> 16);
        data[24 + offset] = (byte) ((lastWX & 0xff000000) >> 24);
        data[31 + offset] = (byte) (lastWY & 0xff);
        data[30 + offset] = (byte) ((lastWY & 0xff00) >> 8);
        data[29 + offset] = (byte) ((lastWY & 0xff0000) >> 16);
        data[28 + offset] = (byte) ((lastWY & 0xff000000) >> 24);
    }

    //传送分段：n个Player+{Player.x+Player.y+Player.pianYiX+Player.pianYiY+Player.dir+Player.num}+MapName+HOSTUI+Player.Names
    public void sendMoving(int cmd) {
        try {
            int playerNum = 1 + FCMutilPlayCache.getTeamMembers().size();
            String playerNames = FCRMaster.gameSave.HOST_UID + "#" + FCRMaster.player1.getName();
            for (FCRPlayerLink link : FCMutilPlayCache.getTeamMembers()) {
                playerNames = playerNames + "@" + link.curPlayerHostUID + "#" + link.curPlayerName;
            }
            String wrap = FCRMaster.player1.getMapname() + "," + playerNames;
            byte[] wrapBytes = wrap.getBytes();
            byte[] data = new byte[1 + playerNum * 32 + wrapBytes.length];
            System.arraycopy(wrapBytes, 0, data, 1 + playerNum * 32, wrapBytes.length);
            data[0] = (byte) (playerNum & 0xff);
            fillMovingData(data, 1, FCRMaster.player1);
            for (int i = 0; i < FCMutilPlayCache.getTeamMembers().size(); i++) {
                FCRPlayerLink link = FCMutilPlayCache.getTeamMembers().get(i);
                FCPlayerInfo info = FCMutilPlayCache.findPlayerByName(link.curPlayerHostUID, link.curPlayerName);
                fillMovingData(data, 33 + i * 32, info);
            }
            plcInterface.sendData(socketKey,cmd, data);
        } catch (Exception e) {
        }
    }

    //n个Player+{HOSTUI+Player.Names} 这里都是加入别人队伍的，客机和服务端都用这个接口
    public void sendRequestJoinIn(String fromHostId, String toHostId) {
        //队长设置
        fcv.setTeamLeader(toHostId);

        ArrayList<FCPlayerInfo> fcPlayerInfos = new ArrayList<>();
        fcPlayerInfos.add(FCRMaster.player1);
        //主动标记下
        fcv.setInTeamLink(true);
        fcv.setBindingPlayerName(null);
        for(FCRPlayerLink link: FCMutilPlayCache.getTeamMembers()){
            FCPlayerInfo p = FCMutilPlayCache.findPlayerByName(link.curPlayerHostUID, link.curPlayerName);
            if(p != null) {
                fcPlayerInfos.add(p);
                //不是玩家的不用设置是否在队伍中
            }
        }
        int playerNum = fcPlayerInfos.size();
        String playerNames = fromHostId+"@"+toHostId;
        for (FCPlayerInfo link : fcPlayerInfos) {
            if (playerNames.equals("")) {
                playerNames = link.getAliasUID() + "@" + link.getName();
            } else {
                playerNames = playerNames + "@" + link.getAliasUID() + "@" + link.getName();
            }
        }
        byte[] wrapBytes = playerNames.getBytes();
        byte[] data = new byte[1 + wrapBytes.length];
        System.arraycopy(wrapBytes, 0, data, 1, wrapBytes.length);
        data[0] = (byte) (playerNum & 0xff);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_JOIN, data);

        //TODO 记住要判断是否有牵引物，有牵引物，也要把牵引发过去加入
        FCPropulsion find = fcv.findPropulsionByHostId(gameSave.HOST_UID);
        if(find != null) {
            byte[] targetHostb = toHostId.getBytes();
            byte[] bytes2 = find.getNetTransportString();
            byte[] senddata = new byte[4+targetHostb.length+bytes2.length];
            int len = targetHostb.length;
            senddata[3] = (byte) (len & 0xff);
            senddata[2] = (byte) ((len & 0xff00) >> 8);
            senddata[1] = (byte) ((len & 0xff0000) >> 16);
            senddata[0] = (byte) ((len & 0xff000000) >> 24);
            System.arraycopy(targetHostb, 0, senddata, 4,len);
            System.arraycopy(bytes2, 0, senddata, 4+len,bytes2.length);
            plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_JOIN_TEAM_FCPropulsion, senddata);
        }
    }


    //申请加入
    public void sendRequestJoinYou() {
        fcv.setLockClickPlayerHost(true);
        String fromToData = gameSave.HOST_UID+"@"+fcv.getCurTeamMenuClickPlayerHost();
        byte[] fromToDatabs = fromToData.getBytes();
        byte[] bytes = new byte[1+fromToDatabs.length];//0 是加入 1是邀请
        bytes[0] = 0;
        System.arraycopy(fromToDatabs,0,bytes, 1,fromToDatabs.length);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_REQUEST_JOIN, bytes);
    }

    //邀请组队
    public void sendRequestJoinMe() {
        fcv.setLockClickPlayerHost(true);
        String fromToData = gameSave.HOST_UID+"@"+fcv.getCurTeamMenuClickPlayerHost();
        byte[] fromToDatabs = fromToData.getBytes();
        byte[] bytes = new byte[1+fromToDatabs.length];//0 是加入 1是邀请
        bytes[0] = 1;
        System.arraycopy(fromToDatabs,0,bytes, 1,fromToDatabs.length);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_REQUEST_JOIN, bytes);
    }

    //回答组队请求
    public void sendRepoRequestJoin(boolean yesOrNo) {
        String fromToData = gameSave.HOST_UID+"@"+fcv.getTeamReqeuestFromWho();
        byte[] fromToDatab = fromToData.getBytes();
        byte[] bytes = new byte[2+fromToDatab.length];
        bytes[0] = yesOrNo ? (byte) 0x1 : 0;
        bytes[1] = (byte)(FCRMaster.fcv.getTeamRequestWay()&0xFF);
        System.arraycopy(fromToDatab, 0, bytes,2,fromToDatab.length);

        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_REPO, bytes);

        if(yesOrNo){
            //答应了，耶耶耶耶耶
            if (FCRMaster.fcv.getTeamRequestWay() == 1){
                //你加进去
                sendRequestJoinIn(gameSave.HOST_UID, fcv.getTeamReqeuestFromWho());
            }else {
                //对方加入来,等就是了，不用做啥
            }
        }
    }

    //TODO 同步全部tankSaveIos，只能给服务端的用
    public void sendAllTanksSync(){
        ArrayList<FCTank> arrayList = new ArrayList<>(FCRMaster.gameSave.getTankSaveIos().size());
        FCRMaster.gameSave.getTankSaveIos().forEach(new BiConsumer<String, FCTank>() {
            @Override
            public void accept(String s, FCTank tank) {
                arrayList.add(tank);
            }
        });
        arrayList.addAll(FCMutilPlayTankCache.mutilTanks);
        String data = gson.toJson(arrayList);
        String compress = FCMixUtil.compress(data);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_RES_TANKIOS, compress.getBytes());
    }

    public void sendTanksSync(){
        //TODO 同步gameSave.tankSaveIos
        ArrayList<FCTank> arrayList = new ArrayList<>(FCRMaster.gameSave.getTankSaveIos().size());
        FCRMaster.gameSave.getTankSaveIos().forEach(new BiConsumer<String, FCTank>() {
            @Override
            public void accept(String s, FCTank tank) {
                arrayList.add(tank);
            }
        });
        String data = gson.toJson(arrayList);
        String compress = FCMixUtil.compress(data);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_RES_TANKIOS, compress.getBytes());
    }

    public void sendFCJumpEvent(String eventName, String map){
        String data = map+"@"+eventName;
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SEND_JUMP_EVENT, data.getBytes());
    }
    /**
     * TODO 战斗通讯==============================================================
     */
    //战斗开始进入,只有队长可以发起
    public void sendBattleStart(){
        FCBattlePack pack = new FCBattlePack();
        for(FCMonster monster:FCRMaster.fcv.getBattleMonster()){
            pack.monsterId.add(monster.getName());
        }
        pack.battleWraps.addAll(FCRMaster.fcv.getBattleWraps());
        pack.monsterCoors.addAll(FCRMaster.fcv.getBattleMonsterCoor());
        pack.randomVs.addAll(FCRMaster.fcv.getMutilPlayRandomV());
        pack.battleEventId = FCRMaster.fcv.getBattleEvent()!=null?FCRMaster.fcv.getBattleEvent().getName():null;
        pack.bossRecord = FCRMaster.fcv.getBattleBossRecord();
        pack.buildCoorMaxMonsterW = fcrMaster.fcMonsterBuildCoor.getMaxMonsterW();
        pack.buildCoorLeftPadding = fcrMaster.fcMonsterBuildCoor.getLeftPadding();
        Integer[] coor = fcrMaster.fcMonsterBuildCoor.getLastCoor();
        pack.buildCoorLastCoor = new int[]{coor[0], coor[1], coor[2],coor[3],coor[4],coor[5],coor[6]};
        String data = gson.toJson(pack);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_BATTLE_JUMP, data.getBytes());
    }

    //角色已经选好技能，回合准备好，把自己ready的wrap对象通知给对方就行了
    public void sendPlayerBattleReady(FCPlayerBattleWrap s){
        String data = gson.toJson(s);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_BATTLE_WRAP_SYNC, data.getBytes());
    }
    /**
     * TODO 战斗通讯==============================================================
     */
    public void sendPlayerSyncEquip(FCPlayerInfo p){
        HashMap<String, String> map = new HashMap<>();
        map.put("hostId", p.getAliasUID());
        map.put("name", p.getName());
        map.put("arm", p.getArm());
        map.put("pants", p.getPants());
        map.put("shoes", p.getShoes());
        map.put("hat", p.getHat());
        map.put("jacket", p.getJacket());
        map.put("glove", p.getGlove());
        String data = gson.toJson(map);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SYNC_EQUIP, data.getBytes());
    }

    public void sendFCPropulsion(FCPropulsion fcPropulsion){
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SYNC_FCPropulsion, fcPropulsion.getNetTransportString());
    }

    //一次性同步当前要共享显示的对象
    public void sendAllFCPropulsion(){
        Iterator<Map.Entry<String,FCPropulsion>> iterator = FCMutilPlayPropulsionCache.propulsioMap.entrySet().iterator();
        StringBuilder sp = new StringBuilder();
        while (iterator.hasNext()){
            FCPropulsion fcPropulsion = iterator.next().getValue();
            byte[] s = fcPropulsion.getNetTransportString();
            sp.append(new String(s));
        }
        byte[] sendData = sp.toString().getBytes();
        if(sendData.length > 0) {
            plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SYNC_FCPropulsion, sendData);
        }
    }
    //上下坦克同步
    public void sendPlayerUpDownTank(FCPlayerInfo p) {
        String data = p.getAliasUID()+","+p.getName()+","+p.getPlayertank1()+","+p.getPlayertankHostId();
        byte[] databs = data.getBytes();
        byte[] bytes = new byte[1+databs.length];
        bytes[0] = 0;
        if(p.getPlayertank1() != null && !p.getPlayertank1().equals("null")){
            bytes[0] = 1;
        }
        System.arraycopy(databs,0,bytes,1,databs.length);
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_SYNC_UPDOWN_TANK, bytes);
    }


    /**
     * 通知所有客机，有小伙伴离开了我们
     * TODO 只能是服务机能调用这个接口
     */
    public void sendNotifyAPlayerExitGame(String hostId){
        plcInterface.sendData(socketKey,FCRSocketConstant.COMMON_S2C_PLAYER_QUIT_GAME, hostId.getBytes());
    }
}
